﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics.CodeAnalysis;
using System.Timers;

namespace NCM_MSTest.Alg
{
    /// <summary>
    /// 插值
    /// </summary>
    public class Interpolation
    {
        /// <summary>
        /// 线性插值（两点差值）
        /// </summary>
        /// <param name="xs"></param>
        /// <param name="ys"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public static void LinearInterpolation(double[] xs, double[] ys, double x, out double y)
        {
            int i = 0;
            y = ys[i] * (x - xs[i + 1]) / (xs[i] - xs[i + 1])
                + ys[i + 1] * (x - xs[i]) / (xs[i + 1] - xs[i]);
        }

        /// <summary>
        ///  二次插值（三点插值）
        /// </summary>
        /// <param name="xs"></param>
        /// <param name="ys"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        public static void TwiceThreePointInterpolation(double[] xs, double[] ys, double x, out double y)
        {
            int i = 1;
            y = ys[i - 1] * (x - xs[i]) * (x - xs[i + 1]) / ((xs[i - 1] - xs[i]) * (xs[i - 1] - xs[i + 1]))
                + ys[i] * (x - xs[i - 1]) * (x - xs[i + 1]) / ((xs[i] - xs[i - 1]) * (xs[i] - xs[i + 1]))
                + ys[i + 1] * (x - xs[i - 1]) * (x - xs[i]) / ((xs[i + 1] - xs[i - 1]) * (xs[i + 1] - xs[i]));
        }

        public static void LagrangeN(int n, double[] x, double[] y, double x1, ref double y1)
        {
            y1 = 0;
            for (int i = 0; i < n; i++)
            {
                double h = 1;
                for (int j = 0; j < n; j++)
                {
                    if (i != j)
                        h = h * (x1 - x[j]) / (x[i] - x[j]);
                }
                y1 = y1 + h * y[i];
            }
        }

        /// <summary>
        /// n阶拉格朗日插值计算
        /// </summary>
        /// <param name="n"></param>
        /// <param name="x">插值节点</param>
        /// <param name="y">函数样本值</param>
        /// <param name="m">插值点的数量</param>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        public static void LagrangeN(int n, double[] x, double[] y, int m, double[] x1, ref double[] y1)
        {
            for (int k = 0; k < m; k++)
            {
                y1[k] = 0;
                for (int i = 0; i < n; i++)
                {
                    double h = 1;
                    for (int j = 0; j < n; j++)
                    {
                        if (i != j)
                            h = h * (x1[k] - x[j]) / (x[i] - x[j]);
                    }
                    y1[k] = y1[k] + h * y[i];
                }
            }
        }
    }
}
